home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (C) 1993, 1994 Marc Parmet.
- * This file is part of the Macintosh port of GNU Emacs.
- *
- * GNU Emacs is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
- #if defined(THINK_C)
- #include <MacHeaders>
- #else
- #include <Types.h>
- #include <Memory.h>
- #include <Quickdraw.h>
- #include <Windows.h>
- #include <TextEdit.h>
- #include <Errors.h>
- #include <Resources.h>
- #endif
-
- #include <Aliases.h>
- #include "unix-types.h"
-
- static struct {
- char *f;
- unsigned char *p[100];
- int n;
- } path;
-
- static void
- colons_to_slashes(char *s,int len)
- {
- int i;
-
- for (i = 0; i<len; ++i)
- if (s[i] == ':') s[i] = '/';
-
- if (len > 0 && s[0] == '.') s[0] = '•';
- }
-
- void
- slashes_to_colons(char *s,int len)
- {
- int i;
-
- for (i = 0; i<len; ++i)
- if (s[i] == '/') s[i] = ':';
-
- if (len > 0 && s[0] == '•') s[0] = '.';
- }
-
- static int
- slash_at_or_after(int i)
- {
- while (1) {
- if (path.f[i] == '\0') return i;
- if (path.f[i] == '/') return i;
- ++i;
- }
- }
-
- static void
- breakup_absolute_unix_pathname(void)
- {
- int i,j,last_component;
-
- path.n = 0;
- i = 1;
- last_component = 0;
- while (1) {
- j = slash_at_or_after(i);
- if (i == j) break;
- last_component = (path.f[j] == '\0');
- path.f[j] = '\0';
- path.p[path.n] = (unsigned char *)path.f + i;
- CtoPstr((char *)path.p[path.n]);
- ++path.n;
- if (last_component) break;
- i = j+1;
- }
- }
-
- static int
- find_FSSpec(FSSpec *spec,int stop_at_alias)
- {
- int i,err;
- short parent_vRef;
- long parent_dirID;
- Boolean wasAliased,isFolder;
- CInfoPBRec pb;
- HParamBlockRec pb2;
- unsigned char *next_name;
- int at_root;
- unsigned char s[256];
-
- at_root = 1;
- next_name = path.p[i = 0];
-
- while (i < path.n) {
- if (!pstrcmp(next_name,"\p."))
- next_name = path.p[++i];
- else if (!pstrcmp(next_name,"\p..")) {
- if (at_root || parent_dirID == fsRtDirID) {
- at_root = 1;
- next_name = path.p[++i];
- }
- else {
- pb.dirInfo.ioNamePtr = s;
- pb.dirInfo.ioFDirIndex = -1;
- pb.dirInfo.ioVRefNum = parent_vRef;
- pb.dirInfo.ioDrDirID = parent_dirID;
- err = PBGetCatInfo(&pb,0);
- if (err) return err;
- pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID;
- err = PBGetCatInfo(&pb,0);
- if (err) return err;
- err = FSMakeFSSpec(pb.dirInfo.ioVRefNum,pb.dirInfo.ioDrParID,s,spec);
- if (err) return err;
- parent_vRef = pb.dirInfo.ioVRefNum;
- parent_dirID = pb.dirInfo.ioDrParID;
- next_name = path.p[++i];
- }
- }
- else {
- pstrcpy(s,next_name);
- colons_to_slashes((char *)s+1,s[0]);
- if (at_root) {
- pstrcat(s,"\p:");
- pb2.volumeParam.ioNamePtr = s;
- pb2.volumeParam.ioVolIndex = -1;
- pb2.volumeParam.ioVRefNum = 0;
- err = PBHGetVInfo(&pb2,0);
- if (err) return err;
-
- parent_vRef = pb2.volumeParam.ioVRefNum;
- parent_dirID = fsRtDirID;
- err = FSMakeFSSpec(pb2.volumeParam.ioVRefNum,fsRtDirID,0L,spec);
- if (err) return err;
- next_name = path.p[++i];
- at_root = 0;
- }
- else {
- pb.dirInfo.ioNamePtr = s;
- pb.dirInfo.ioFDirIndex = 0;
- pb.dirInfo.ioVRefNum = parent_vRef;
- pb.dirInfo.ioDrDirID = parent_dirID;
- err = PBGetCatInfo(&pb,0);
- if (i == path.n-1 && err == fnfErr) {
- err = FSMakeFSSpec(pb.dirInfo.ioVRefNum,pb.dirInfo.ioDrDirID,
- pb.dirInfo.ioNamePtr,spec);
- return err;
- }
- if (err == fnfErr) return dirNFErr;
- if (err) return err;
-
- err = FSMakeFSSpec(pb.dirInfo.ioVRefNum,pb.dirInfo.ioDrParID,
- pb.dirInfo.ioNamePtr,spec);
- if (err) return err;
- if (i == path.n-1 && stop_at_alias) break;
- err = ResolveAliasFile(spec,-1,&isFolder,&wasAliased);
- if (err) return err;
- if (wasAliased) {
- parent_vRef = spec->vRefNum;
- parent_dirID = spec->parID;
- next_name = spec->name;
- }
- else {
- parent_vRef = pb.dirInfo.ioVRefNum;
- parent_dirID = pb.dirInfo.ioDrDirID;
- next_name = path.p[++i];
- }
- }
- }
- }
-
- if (at_root) return nsDrvErr;
- return noErr;
- }
-
- static int
- getemacsdir(Handle *u)
- {
- int i;
- FCBPBRec pb;
- unsigned char name[256];
- /* Handle rsrc,h; */
- Handle h;
- short err,refNum;
- FSSpec spec;
- static Handle t;
-
- if (t == 0L) {
- /* GetAppParms(name,&refNum,&h); */
- h = GetResource('STR ',128); // Something always available
- if (h == 0L) return resNotFound;
- refNum = HomeResFile(h);
- err = ResError();
- if (err) return err;
-
- pb.ioNamePtr = name;
- pb.ioRefNum = refNum;
- pb.ioFCBIndx = 0;
- err = PBGetFCBInfo(&pb,0);
- if (err) return err;
- err = FSMakeFSSpec(pb.ioFCBVRefNum,pb.ioFCBParID,pb.ioNamePtr,&spec);
- if (err) return err;
- err = FSSpec2unixfn_internal(&spec,&t);
- if (err) return err;
- HLock(t);
- i = strlen(*t) - 1;
- HUnlock(t);
- while (1) {
- if (i == 0) return dirNFErr;
- if ((*t)[i] == '/') break;
- --i;
- }
- (*t)[i+1] = '\0';
- }
-
- HLock(t);
- *u = NewHandle(strlen(*t) + 1);
- err = MemError();
- HUnlock(t);
- if (err) return err;
- HLock(t);
- HLock(*u);
- strcpy(**u,*t);
- HUnlock(t);
- HUnlock(*u);
- return 0;
- }
-
- static int
- based_on_emacs(char *extra1,char *extra2)
- {
- int err;
- Handle t;
-
- err = getemacsdir(&t);
- if (err) return err;
- HLock(t);
- path.f = NewPtr(strlen(*t) + strlen(extra1) + strlen(extra2) + 1);
- err = MemError();
- if (err) { DisposHandle(t); return err; }
- strcpy(path.f,*t);
- strcat(path.f,extra1);
- strcat(path.f,extra2);
- DisposHandle(t);
- return 0;
- }
-
- static int
- get_directories(char *t)
- {
- short err;
- unsigned char **u = (unsigned char **)GetResource('STR ',128);
- if (err = ResError()) return err;
- HLock((Handle)u);
- pstrcpy((unsigned char *)t,*u);
- HUnlock((Handle)u);
- PtoCstr((unsigned char *)t);
- strcat(t,"/");
- return 0;
- }
-
- static int
- convert_path(FSSpec *fs,int stop_at_alias)
- {
- int err;
-
- breakup_absolute_unix_pathname();
- err = find_FSSpec(fs,stop_at_alias);
- DisposPtr(path.f);
- return err;
- }
-
- int
- unixfn2FSSpec_internal(char *s,FSSpec *fs,int stop_at_alias)
- {
- int i,err,cwdlen;
- static struct ghost {
- char *false_target,*true_target;
- } ghosts[] = {
- "/tmp", "",
- "/usr/tmp", "",
- "/bin", "etc/",
- "/etc", "etc/",
- "~emacs", "",
- };
- static int nghosts = sizeof(ghosts) / sizeof(struct ghost);
-
- if (strlen(s) == 0) return bdNamErr;
-
- for (i = 0; i<nghosts; ++i) {
- if (!strcmp(s,ghosts[i].false_target)) {
- err = based_on_emacs(ghosts[i].true_target,"");
- if (err) return err;
- return convert_path(fs,stop_at_alias);
- }
- else {
- char t[256];
- strcpy(t,ghosts[i].false_target);
- strcat(t,"/");
- if (!strncmp(s,t,strlen(t))) {
- err = based_on_emacs(ghosts[i].true_target,s + strlen(t));
- if (err) return err;
- return convert_path(fs,stop_at_alias);
- }
- }
- }
-
- if (s[0] == '~' && s[1] != '\0') {
- if (!strncmp(s,"~/",2)) {
- char t[256];
- err = get_directories(t);
- if (err) return err;
- strcat(t,"home/");
- err = based_on_emacs(t,s+2);
- if (err) return err;
- err = convert_path(fs,stop_at_alias);
- if (err) {
- err = based_on_emacs("",s+2);
- if (err) return err;
- err = convert_path(fs,stop_at_alias);
- return err;
- }
- else
- return noErr;
- }
- else {
- char t[256];
- err = get_directories(t);
- if (err) return err;
- err = based_on_emacs(t,s+1);
- if (err) return err;
- return convert_path(fs,stop_at_alias);
- }
- }
-
- if (s[0] == '/') {
- path.f = NewPtr(strlen(s)+1);
- strcpy(path.f,s);
- return convert_path(fs,stop_at_alias);
- }
- else {
- if (proctable[current_process_index].cwd_string == 0L) return dirNFErr;
- cwdlen = strlen(proctable[current_process_index].cwd_string);
- path.f = NewPtr(strlen(s) + cwdlen + 2);
- strcpy(path.f,proctable[current_process_index].cwd_string);
- if (path.f[cwdlen-1] != '/') strcat(path.f,"/");
- strcat(path.f,s);
- if (path.f[0] == '~') {
- char *g = path.f;
- err = unixfn2FSSpec_internal(g,fs,stop_at_alias);
- DisposPtr(g);
- return err;
- }
- else
- return convert_path(fs,stop_at_alias);
- }
- }
-